﻿/***************************************************************************
	Copyright (C) 2010 RapidWebDev Organization (Author: Eunge, Legal Name: Jian Liu, Email: eunge.liu@gmail.com)

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ***************************************************************************/

using System;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using BaoJianSoft.Common;
using BaoJianSoft.Web.Extensions.Controls;
using BaoJianSoft.Web.Extensions.Properties;

namespace BaoJianSoft.Web.Extensions.DynamicPages
{
    /// <summary>
    /// Abstract class to edit/view detail panel.
    /// </summary>
    public abstract class PageWorkshop : IPageWorkshop
    {
        private static readonly Type bindingAttributeType = typeof(BindingAttribute);

        /// <summary>
        /// The session key of current entity id in detail panel.
        /// </summary>
        public const string CURRENT_ENTITY_ID = "CurrentEntityId";

        /// <summary>
        /// The session key of current entity editing mode.
        /// </summary>
        public const string EDITING_MODE = "EditingMode";

        /// <summary>
        /// The session key of whether the detail panel background color is transparent.
        /// </summary>
        public const string TRANSPARENT_DETAIL_PANEL = "TransparentDetailPanel";

        /// <summary>
        /// The session key of whether the summary panel background color is transparent.
        /// </summary>
        public const string TRANSPARENT_SUMMARY_PANEL = "TransparentSummaryPanel";

        #region Interface IPage Members

        /// <summary>
        /// The event fires by detail panel to display message.
        /// </summary>
        public event EventHandler<MessageEventArgs> Messaging;

        /// <summary>
        /// Set/get page workshop configuration to build up web page.
        /// </summary>
        public virtual PageWorkshopConfiguration Configuration { get; set; }

		/// <summary>
		/// Find entities by predicate clauses.
		/// </summary>
		/// <param name="args">Data source loading event argument</param>
		/// <returns>Return list of objects</returns>
		public virtual void OnQuerying(DataSourceLoadEventArgs args) { args.DataSource = null; args.RecordCount = 0; }

        /// <summary>
        /// Delete content by entity id.
        /// </summary>
        /// <param name="entityId"></param>
        public virtual void OnDeleting(string entityId) { }

        /// <summary>
        /// Create a blank detail panel form.
        /// </summary>
        public virtual void OnCreateBlankDetailPanel() { }

        /// <summary>
        /// Show detail panel to edit specified entity by id.
        /// </summary>
        /// <param name="entityId"></param>
        public virtual void OnShowEditableDetailPanel(string entityId) { }

        /// <summary>
        /// Show detail panel to view specified entity by id.
        /// </summary>
        /// <param name="entityId"></param>
        public virtual void OnShowViewableDetailPanel(string entityId) { }

        /// <summary>
        /// Create new entity displayed in detail panel.
        /// </summary>
        public virtual void OnSaving() { }

        /// <summary>
        /// Save (Create/Update) entity displayed inner of detail panel.
        /// </summary>
        /// <param name="entityId"></param>
        public virtual void OnSaving(string entityId) { }

        /// <summary>
        /// Cancel editing in detail panel.
        /// </summary>
        public virtual void OnCancelling() { }

        /// <summary>
        /// Validate editing entity in detail panel in adding mode.
        /// </summary>
        /// <returns>Returns null if detail panel is valid.</returns>
        public virtual string OnValidating() { return null; }

        /// <summary>
        /// Validate entity edited in detail panel. 
        /// </summary>
        /// <param name="entityId"></param>
        /// <returns>Returns null if detail panel is valid.</returns>
        public virtual string OnValidating(string entityId) { return null; }

        /// <summary>
        /// The method will be invoked when prepare to render detail panel.
        /// </summary>
        public virtual void OnPreRende(Page webpage) { }

        /// <summary>
        /// On GridView buttons binding.
        /// </summary>
        /// <param name="e"></param>
        public virtual void OnBindingGridViewButtons(GridViewButtonBindingEventArgs e) { }

        /// <summary>
        /// On GridView checkbox binding.
        /// </summary>
        /// <param name="e"></param>
        public virtual void OnBindingGridViewCheckBox(GridViewCheckBoxBindingEventArgs e) { }

        /// <summary>
        /// On interactive buttons binding.
        /// </summary>
        /// <param name="e"></param>
        public virtual void OnRenderingInteractiveControls(InteractiveControlsEventArgs e) { }

        /// <summary>
        /// On attaching child controls. 
        /// The method attempts to load control from skin template by field name for the fields declared with BindingAttribute
        /// </summary>
        /// <param name="detailpanel"></param>
        public virtual void OnAttachDetailPanelControls(TemplatePanel detailpanel)
        {
            this.AttachControls(detailpanel);
        }

        /// <summary>
        /// On attaching controls in summary panel.
        /// </summary>
        /// <param name="detailpanel"></param>
        public virtual void OnAttachSummaryPanelControls(TemplatePanel detailpanel)
        {
            this.AttachControls(detailpanel);
        }

        /// <summary>
        /// On WorkshopAspxPageBase initialized.
        /// </summary>
        /// <param name="page"></param>
        public virtual void BeforeInit(WorkshopAspxPageBase page) { }

        /// <summary>
        /// On WorkshopAspxPageBase loaded.
        /// </summary>
        /// <param name="page"></param>
        public virtual void OnLoaded(WorkshopAspxPageBase page) { }

        /// <summary>
        /// On generic button clicked.
        /// </summary>
        /// <param name="commandArgument">Configured linkbutton command argument</param>
        /// <param name="entityIds">A collection of checked gridview items. Null if CheckBox column is not configured.</param>
        public virtual void OnGenericButtonClicked(string commandArgument, IEnumerable<string> entityIds)
        {
        }

        /// <summary>
        /// On submitting summary panel.
        /// </summary>
        /// <param name="entityIds">A collection of checked gridview items. Null if CheckBox column is not configured.</param>
        public virtual void OnSubmitSummaryPanel(IEnumerable<string> entityIds) { }

        #endregion

        #region Methods ShowMessage

        /// <summary>
        /// Show unpredictable fault message
        /// </summary>
        protected void ShowMessage()
        {
            if (this.Messaging != null)
            {
                this.Messaging(this, new MessageEventArgs(MessageTypes.Error, Resources.UnknowError));
            }
        }

        /// <summary>
        /// Show message
        /// </summary>
        /// <param name="messageType"></param>
        /// <param name="messageBody"></param>
        protected void ShowMessage(MessageTypes messageType, string messageBody)
        {
            if (this.Messaging != null)
            {
                this.Messaging(this, new MessageEventArgs(messageType, messageBody));
            }
        }

        /// <summary>
        /// Show message
        /// </summary>
        /// <param name="messageType"></param>
        /// <param name="messageFormat"></param>
        /// <param name="parameters"></param>
        protected void ShowMessage(MessageTypes messageType, string messageFormat, params object[] parameters)
        {
            if (this.Messaging != null)
            {
                this.Messaging(this, new MessageEventArgs(messageType, string.Format(messageFormat, parameters)));
            }
        }

        #endregion

        private void AttachControls(TemplatePanel detailpanel)
        {
            Type thisType = this.GetType();
            FieldInfo[] fields = thisType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (FieldInfo field in fields)
            {
                object[] bindings = field.GetCustomAttributes(bindingAttributeType, true);
                if (bindings == null || bindings.Length == 0) continue;

                // Last attribute overrides all before
                BindingAttribute binding = bindings[bindings.Length - 1] as BindingAttribute;

                Control findControl = null;
                if (Kit.IsEmpty(binding.ParentControlPath))
                {
                    findControl = detailpanel.FindControl(field.Name);
                }
                else
                {
                    string[] parentControlIds = binding.ParentControlPath.Split(new string[] { @"\", "/" }, StringSplitOptions.RemoveEmptyEntries);
                    Control parentControl = detailpanel;
                    foreach (string parentControlId in parentControlIds)
                    {
                        if (parentControl == null) throw new InvalidProgramException(string.Format(Resources.ParentControlNotFoundInSkinTemplate, binding.ParentControlPath, detailpanel.SkinPath));
                        parentControl = parentControl.FindControl(parentControlId);
                    }

                    findControl = parentControl.FindControl(field.Name);
                }

                if (findControl != null)
                    field.SetValue(this, findControl);
            }
        }
    }

    /// <summary>
    /// Editing modes of current entity.
    /// </summary>
    public enum EditingModes { None, Edit, View }
}

